package edu.ccut.saturn.basecomponent.database.util;

import java.util.List;

import edu.ccut.saturn.basecomponent.database.IDeleteSQLBuilder;
import edu.ccut.saturn.basecomponent.database.ISaturnSQL;
import edu.ccut.saturn.basecomponent.database.ISaturnSQLBuilder;
import edu.ccut.saturn.basecomponent.database.ISelectSQLBuilder;
import edu.ccut.saturn.basecomponent.database.IUpdateSQLBuilder;
import edu.ccut.saturn.component.IDataInfo;
import edu.ccut.saturn.component.IDataItem;
import edu.ccut.saturn.component.ILogicContext;
import edu.ccut.saturn.component.IParameterContext;
import edu.ccut.saturn.component.SaturnData;

public class SaturnSQLUtil {

	private static final String SEPARATE = ConditionUtils.SEPARATE;

	private static final String[] specialColumn = { "CHAR", "TRIM(", ")",
			"DATE", "TO_CHAR(", ",'YYYY-MM-DD HH24:MI:SS')" };

	public static boolean isNull(Object value) {
		if (value == null) {
			return true;
		}
		return false;
	}

	public static String GetDynamicCondition(List<String> expList,
			IParameterContext parameterContext) {
		StringBuffer whereCondition = new StringBuffer();
		StringBuffer part = new StringBuffer().append("");
		for (String exp : expList) {
			if (exp != null)
				part.replace(0, part.length(), parseString(exp,
						parameterContext, false));
			if (!"".equals(part.toString())) {
				whereCondition.append(" AND ").append(part);
			}
		}
		return whereCondition.toString();
	}

	/**
	 * 解析大括号中的内容，得到新的String user.name -> aa n == ${user.name} + ${user.age} -> n ==
	 * 'aa' + '10'
	 * 
	 * @param condition
	 *            形如 'user.age between ${startAge} and ${endAge}' 'user.name
	 *            =${user.name}'
	 * @param parameterContext
	 * @param continueParse
	 *            true 参数为空也不阻止解析，false 则返回空字符串
	 * @return 如果字符串中参数为空则
	 */
	public static String parseString(String condition,
			IParameterContext parameterContext, boolean continueParse) {
		StringBuffer newCondition = new StringBuffer().append(""); //$NON-NLS-1$
		char[] charArray = condition.toCharArray();
		StringBuffer oldexp = new StringBuffer();// ${}表达式
		boolean isGetExp = false; // 是否在拼${}表达式
		boolean is$ = false;
		for (char currItem : charArray) {
			if (is$) {
				if (currItem == '{') {
					// 开始拼表达式
					isGetExp = true;
					oldexp.append("${");
				} else {
					// 只是普通$符号
					newCondition.append("$").append(currItem);
				}
				is$ = false;
			} else {
				if (isGetExp) {
					if (currItem != '}') {
						oldexp.append(currItem);
					} else {
						oldexp.append(currItem);
						isGetExp = false;
						// 解析
						Object value = parameterContext
								.getLogicContextValue(oldexp.toString());
						// if(newCondition.toString().endsWith("%")){
						// //在拼like表达式 ，不需要''
						// newCondition.append(value);
						// }else{
						// newCondition.append(value);
						// }
						if (value != null
								&& !"".equals(((String) value).trim())) {
							newCondition.append(value);
						} else {
							if (continueParse) {
								newCondition.append("");
							} else {
								return "";
							}
						}
						oldexp.delete(0, oldexp.length());
					}
				} else {
					if (currItem != '$') {
						newCondition.append(currItem);
					} else {
						// 判断是否开始拼表达式
						is$ = true;
					}
				}
			}
		}
		return newCondition.toString();
	}

	/**
	 * 通过给入的参数上下文(parameterContext),builder,处理类型
	 * 
	 */
	@SuppressWarnings("unchecked")
	public static ISaturnSQL getSaturnSQL(IParameterContext parameterContext,
			ISaturnSQLBuilder builder, String operation) throws Exception {
		IDeleteSQLBuilder deleteSQLBuilder = null;
		IUpdateSQLBuilder updateSQLBuilder = null;
		ISelectSQLBuilder selectSQLBuilder = null;

		if (operation.contains("UPDATE")) {
			updateSQLBuilder = builder.getUpdateSQLBuilder(operation);
		}
		if (operation.contains("DELETE")) {
			deleteSQLBuilder = builder.getDeleteSQLBuilder(operation);
		}
		if (operation.contains("COUNT")) {
			selectSQLBuilder = builder.getSelectSQLBuilder(operation);
		}
		if (operation.equals("SELECT") || operation.equals("SELECT.LOB")) {
			selectSQLBuilder = builder.getSelectSQLBuilder(operation);
		}
		Object keyObject = parameterContext.getParameterValue(0);
		String dbType = SaturnDataUtil.getStandardDBType(keyObject);
		List<FieldAndValueVO> list = null;
		String condition = null;

		if (dbType.equals("sqlserver")) {
			String parameterValue1 = (String) parameterContext
					.getParameterValue(1);
			String[] conditions = parameterValue1.split(SEPARATE);

			if (conditions.length == 3) {
				ILogicContext logicContext = parameterContext.getLogicContext();
				String key = conditions[2].trim();
				list = (List<FieldAndValueVO>) logicContext.getValue(key);

				if (list.size() != 0) {
					condition = conditions[1].trim();
				} else {
					condition = conditions[0].trim();
				}
			} else {
				condition = parameterValue1;
			}
		} else {
			condition = (String) parameterContext.getParameterValue(1);
		}

		if (condition == null) {
			condition = "";
		}
		condition = " WHERE 1=1 " + condition;
		String specalColumn = null;
		ISaturnSQL saturnSQL = null;

		if (operation.contains("UPDATE")) {
			specalColumn = (String) parameterContext.getParameterValue(3);
			saturnSQL = updateSQLBuilder.build((SaturnData) keyObject, condition,
					specalColumn);
		}

		if (operation.contains("COUNT")) {
			saturnSQL = selectSQLBuilder.build2((String) keyObject, condition);
		}

		if (operation.contains("DELETE")) {
			saturnSQL = deleteSQLBuilder.build((String) keyObject, condition);
		}

		if (operation.equals("SELECT") || operation.equals("SELECT.LOB")) {
			saturnSQL = selectSQLBuilder.build((String) keyObject, condition);
		}
		saturnSQL.setConditionList(list);
		return saturnSQL;
	}

	public static String parseOracleCondition(String condition,
			Object saturnDataOrFullkey) {
		if (null == condition) {
			return condition;
		}
		IDataInfo dataInfo = SaturnDataUtil.getDataInfo(saturnDataOrFullkey);
		for (String key : dataInfo.keySet()) {
			IDataItem dataItem = dataInfo.getDataItem(key);
			String sqlType = dataItem.getType();
			for (int j = 0; j < specialColumn.length;) {

				if (specialColumn[j].equalsIgnoreCase(sqlType)) {
					j++;
					String replaceTempString = null;
					String tableName = dataItem.getTableName();
					String columnName = dataItem.getColumn();
					String wholeColumnName = " " + tableName + "." + columnName;

					replaceTempString = " " + specialColumn[j++]
							+ wholeColumnName + specialColumn[j++];
					condition = removeConstantSpace(columnName.toUpperCase(),
							condition);
					condition = removeConstantSpace(columnName.toLowerCase(),
							condition);

					condition = condition.replace(
							wholeColumnName.toUpperCase(), replaceTempString);
					condition = condition.replace(
							wholeColumnName.toLowerCase(), replaceTempString);
					condition = condition.replace(" "
							+ columnName.toUpperCase(), replaceTempString);
					condition = condition.replace(" "
							+ columnName.toLowerCase(), replaceTempString);

				} else {
					j += 3;
				}
			}
		}
		return condition;
	}

	private static String removeConstantSpace(String columnName,
			String condition) {
		int fromIndex = 0;
		int columnIndex = -1;
		while ((columnIndex = condition.indexOf(columnName, fromIndex)) != -1) {
			int leftQuoteIndex = condition.lastIndexOf("'", columnIndex);
			int rightQuoteIndex = condition.indexOf("'", columnIndex);
			if (leftQuoteIndex == -1 || rightQuoteIndex == -1
					|| leftQuoteIndex >= rightQuoteIndex) {
				fromIndex = columnIndex + columnName.length();
				continue;
			}
			String subString = condition.substring(leftQuoteIndex + 1,
					rightQuoteIndex);
			if (columnName.equals(subString.trim())) {
				condition = condition.replace("'" + subString + "'", "'"
						+ columnName + "'");
			}
			fromIndex = leftQuoteIndex + columnName.length() + 2;
		}
		return condition;
	}
}
